package com.lyEducation.redisConfig;

import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.time.Duration;

@Configuration
@Getter
public class JedisRedisConfig {
  @Value("${spring.redis.host}")
  private String redisHost;

  @Value("${spring.redis.password}")
  private String redisPassword;

  @Value("${spring.redis.port}")
  private int redisPort;

  @Value("${spring.redis.timeout}")
  private int redisTimeout;

  @Value("${spring.redis.database}")
  private int database;

  @Value("${spring.redis.jedis.pool.min-idle}")
  private int jedisPoolMinIdle;

  @Value("${spring.redis.jedis.pool.max-idle}")
  private int jedisPoolMaxIdle;

  @Value("${spring.redis.jedis.pool.max-wait}")
  private long jedisPoolMaxWaitMillis;

  @Value("${spring.redis.jedis.pool.timeBetweenEvictionRunsMillis}")
  private long timeBetweenEvictionRunsMillis;

  @Value("${spring.redis.jedis.pool.numTestsPerEvictionRun}")
  private int numTestsPerEvictionRun;

  @Value("${spring.redis.jedis.pool.minEvictableIdleTimeMillis}")
  private long minEvictableIdleTimeMillis;

  @Value("${spring.redis.jedis.pool.max-active}")
  private int jedisPoolMaxActive;

  @Value("${spring.redis.jedis.shutdown-timeout}")
  private int jedisShutdownTimeout;
  // JedisConnectionFactory JedisPool 无法使用同一JedisPoolConfig对象 会导致RedisTemplate无法生存
  //  private final JedisPoolConfig jedisPoolConfig;

  @Bean
  JedisConnectionFactory jedisConnectionFactory() {
    //    JedisConnectionFactory factory = new JedisConnectionFactory();
    //    //    RedisStandaloneConfiguration redisStandaloneConfiguration = new
    //    // RedisStandaloneConfiguration();
    //    //    redisStandaloneConfiguration.setHostName(host);
    //    //    redisStandaloneConfiguration.setPort(port);
    //    factory.setHostName(getRedisHost());
    //    factory.setPort(getRedisPort());
    //    factory.setTimeout(getRedisTimeout());
    //    factory.setPassword(getRedisPassword());
    JedisClientConfiguration jedisClientConfiguration =
            JedisClientConfiguration.builder()
                    .usePooling()
                    .poolConfig(createJedisPoolConfig())
                    .and()
                    .readTimeout(Duration.ofMillis(redisTimeout))
                    .build();
    RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
    redisStandaloneConfiguration.setDatabase(getDatabase());
    redisStandaloneConfiguration.setPort(getRedisPort());
    redisStandaloneConfiguration.setPassword(RedisPassword.of(getRedisPassword()));
    redisStandaloneConfiguration.setHostName(getRedisHost());
    return new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration);
  }

  @Bean
  public JedisPool redisPoolFactory() {
    JedisPool jedisPool =
            new JedisPool(
                    createJedisPoolConfig(),
                    getRedisHost(),
                    getRedisPort(),
                    getRedisTimeout(),
                    getRedisPassword());
    return jedisPool;
  }

  private JedisPoolConfig createJedisPoolConfig() {
    JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
    jedisPoolConfig.setMaxTotal(getJedisPoolMaxActive());
    jedisPoolConfig.setMinIdle(getJedisPoolMinIdle());
    jedisPoolConfig.setMaxIdle(getJedisPoolMaxIdle());
    jedisPoolConfig.setMaxWaitMillis(getJedisPoolMaxWaitMillis());
    jedisPoolConfig.setTestOnBorrow(true);
    jedisPoolConfig.setTestOnReturn(true);
    jedisPoolConfig.setTestWhileIdle(true);
    // idle object evitor两次扫描之间要sleep的时间
    jedisPoolConfig.setTimeBetweenEvictionRunsMillis(getTimeBetweenEvictionRunsMillis());
    // 表示idle object evitor每次扫描的最多的对象数
    jedisPoolConfig.setNumTestsPerEvictionRun(getNumTestsPerEvictionRun());
    // 表示一个对象至少停留在idle状态的最短时间，然后才能被idle object
    // evitor扫描并驱逐；这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义
    jedisPoolConfig.setMinEvictableIdleTimeMillis(getMinEvictableIdleTimeMillis());

    return jedisPoolConfig;
  }
}
